/// 高级特征
/*
本章将要学习的功能在一些非常特定的场景下很有用处。虽然很少会碰到它们，我们希望确保你了解 Rust 提供的所有功能。
本章将涉及如下内容：
    不安全 Rust：用于当需要舍弃 Rust 的某些保证并负责手动维持这些保证
    高级 trait：与 trait 相关的关联类型，默认类型参数，完全限定语法（fully qualified syntax），超（父）trait（supertraits）和 newtype 模式
    高级类型：关于 newtype 模式的更多内容，类型别名，never 类型和动态大小类型
    高级函数和闭包：函数指针和返回闭包
    宏：定义在编译时定义更多代码的方式
对所有人而言，这都是一个介绍 Rust 迷人特性的宝典！让我们翻开它吧！
*/

/// 1、不安全 Rust
/*
目前为止讨论过的代码都有 Rust 在编译时会强制执行的内存安全保证。然而，Rust 还隐藏有第二种语言，它不会强制执行这类内存安全保证：
这被称为 不安全 Rust（unsafe Rust）。它与常规 Rust 代码无异，但是会提供额外的超能力。
尽管代码可能没问题，但如果 Rust 编译器没有足够的信息可以确定，它将拒绝代码。
不安全 Rust 之所以存在，是因为静态分析本质上是保守的。当编译器尝试确定一段代码是否支持某个保证时，它最好拒绝一些有效的程序而不是接受一些无效的程序。
这必然意味着有时代码可能是合法的，但如果 Rust 编译器没有足够的信息来确定，它将拒绝该代码。在这种情况下，可以使用不安全代码告诉编译器，
“相信我，我知道我在干什么。”这么做的缺点就是你只能靠自己了：如果不安全代码出错了，比如解引用空指针，可能会导致不安全的内存使用。
另一个 Rust 存在不安全一面的原因是：底层计算机硬件固有的不安全性。如果 Rust 不允许进行不安全操作，那么有些任务则根本完成不了。
Rust 需要能够进行像直接与操作系统交互，甚至于编写你自己的操作系统这样的底层系统编程！这也是 Rust 语言的目标之一。让我们看看不安全 Rust 能做什么，和怎么做。
*/
/// 不安全的超能力
/*
可以通过 unsafe 关键字来切换到不安全 Rust，接着可以开启一个新的存放不安全代码的块。这里有五类可以在不安全 Rust 中进行而不能用于安全 Rust 的操作，
它们称之为 “不安全的超能力。” 这些超能力是：
    解引用裸指针
    调用不安全的函数或方法
    访问或修改可变静态变量
    实现不安全 trait
    访问 union 的字段
有一点很重要，unsafe 并不会关闭借用检查器或禁用任何其他 Rust 安全检查：如果在不安全代码中使用引用，
它仍会被检查。unsafe 关键字只是提供了那五个不会被编译器检查内存安全的功能。你仍然能在不安全块中获得某种程度的安全。
再者，unsafe 不意味着块中的代码就一定是危险的或者必然导致内存安全问题：其意图在于作为开发者你将会确保 unsafe 块中的代码以有效的方式访问内存。
人是会犯错误的，错误总会发生，不过通过要求这五类操作必须位于标记为 unsafe 的块中，就能够知道任何与内存安全相关的错误必定位于 unsafe 块内。保持 unsafe 块尽可能小，如此当之后调查内存 bug 时就会感谢你自己了。
为了尽可能隔离不安全代码，将不安全代码封装进一个安全的抽象并提供安全 API 是一个好主意，当我们学习不安全函数和方法时会讨论到。
标准库的一部分被实现为在被评审过的不安全代码之上的安全抽象。这个技术防止了 unsafe 泄露到所有你或者用户希望使用由 unsafe 代码实现的功能的地方，因为使用其安全抽象是安全的。
*/
/// 解引用裸指针
fn main() {
    let mut num = 5;

    let r1 = &num as *const i32;
    let r2 = &mut num as *mut i32;

    unsafe {
        println!("r1 is: {}", *r1);
        println!("r2 is: {}", *r2);
    }
}

/// 调用不安全函数或方法

fn main() {
    unsafe fn dangerous() {

    }

    unsafe {
        dangerous();
    }
}

/// 创建不安全代码的安全抽象

fn main() {
    let mut v = vec![1, 2, 3, 4, 5, 6];

    let r = &mut v[..];

    let (a, b) = r.split_at_mut(3);

    assert_eq!(a, &mut [1, 2, 3]);
    assert_eq!(b, &mut [4, 5, 6]);
}


/// 2、宏
/*
我们已经在本书中使用过像 println! 这样的宏了，不过还没完全探索什么是宏以及它是如何工作的。宏（Macro）指的是 Rust 中一系列的功能：
使用 macro_rules! 的 声明（Declarative）宏，和三种 过程（Procedural）宏：
*/